package cn.supermaster.management.common.utils;

import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;

import cn.supermaster.management.common.json.JSON;
import org.apache.shiro.SecurityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * 处理并记录日志文件
 */
public class LogUtils {

    public static final Logger ERROR_LOG = LoggerFactory.getLogger("sys-error");
    public static final Logger ACCESS_LOG = LoggerFactory.getLogger("sys-access");

    /**
     * 记录访问日志 [username][jsessionid][ip][accept][UserAgent][url][params][Referer]
     *
     * @param request
     * @throws Exception
     */
    public static void logAccess(HttpServletRequest request) throws Exception {
        String username = getUsername();
        String jsessionId = request.getRequestedSessionId();
        String ip = AddressUtils.getIPAddress(request);
        String accept = request.getHeader("accept");
        String userAgent = request.getHeader("User-Agent");
        String url = request.getRequestURI();
        String params = getParams(request);

        StringBuilder builder = new StringBuilder();
        builder.append(buildBlock(username));
        builder.append(buildBlock(jsessionId));
        builder.append(buildBlock(ip));
        builder.append(buildBlock(accept));
        builder.append(buildBlock(userAgent));
        builder.append(buildBlock(url));
        builder.append(buildBlock(params));
        builder.append(buildBlock(request.getHeader("Referer")));
        ACCESS_LOG.info(builder.toString());
    }

    /**
     * 记录异常错误 格式 [exception]
     *
     * @param message
     * @param throwable
     */
    public static void logError(String message, Throwable throwable) {
        String username = getUsername();
        StringBuilder builder = new StringBuilder();
        builder.append(buildBlock("exception"));
        builder.append(buildBlock(username));
        builder.append(buildBlock(message));
        ERROR_LOG.error(builder.toString(), throwable);
    }

    /**
     * 记录页面错误 错误日志记录 [page/eception][username][statusCode][errorMessage][servletName][uri][exceptionName][ip][exception]
     *
     * @param request
     */
    public static void logPageError(HttpServletRequest request) {
        String username = getUsername();

        Integer statusCode = (Integer) request.getAttribute("javax.servlet.error.status_code");
        String message = (String) request.getAttribute("javax.servlet.error.message");
        String uri = (String) request.getAttribute("javax.servlet.error.request_uri");
        Throwable throwable = (Throwable) request.getAttribute("javax.servlet.error.exception");

        if (statusCode == null) {
            statusCode = 0;
        }

        //
        StringBuilder builder = new StringBuilder();
        builder.append(buildBlock(throwable == null ? "page" : "exception"));
        builder.append(buildBlock(username));
        builder.append(buildBlock(statusCode));
        builder.append(buildBlock(message));
        builder.append(buildBlock(AddressUtils.getIPAddress(request)));

        builder.append(buildBlock(uri));
        builder.append(buildBlock(request.getHeader("Referer")));
        StringWriter sw = new StringWriter();

        while (throwable != null) {
            throwable.printStackTrace(new PrintWriter(sw));
            throwable = throwable.getCause();
        }
        builder.append(buildBlock(sw.toString()));
        ERROR_LOG.error(builder.toString());

    }

    /**
     * @Description: [构建信息块]
     * <p></P>
     * @Title: buildBlock
     * @Author: Lance Ting
     * @Date: 2021-01-02
     * @Param: block
     * @Return: java.lang.String
     */
    public static String buildBlock(Object block) {
        return String.format("[{}]", ConvertUtils.toText(block, ""));
    }

    protected static String getParams(HttpServletRequest request) throws Exception {
        Map<String, String[]> params = request.getParameterMap();
        return JSON.marshal(params);
    }

    protected static String getUsername() {
        return (String) SecurityUtils.getSubject().getPrincipal();
    }
}
